From: Jasper St. Pierre Date: Sat, 15 Sep 2012 05:38:40 +0000 (-0300) Subject: grabHelper: Rework grabbing code to properly handle stacking X-Git-Tag: archive/raspbian/50.5-1+rpi1~1^2~1013^2^2~5855 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/%22/%22http:/www.example.com/cgi/%22?a=commitdiff_plain;h=b203a95a786af60257e55881c19b45192a0655b8;p=gnome-shell.git grabHelper: Rework grabbing code to properly handle stacking When Dan Winship wrote the GrabHelper code originally, it didn't handle a grab stack. I wrote the grab stack code hastily when landed the message tray, not understanding all of the code that was involved here. Fix it so that we properly do the operations for each type of grab when we first need to, and not sometimes when the first grab is taken. https://bugzilla.gnome.org/show_bug.cgi?id=683546 --- diff --git a/js/ui/grabHelper.js b/js/ui/grabHelper.js index 7120043b8..fee72c51e 100644 --- a/js/ui/grabHelper.js +++ b/js/ui/grabHelper.js @@ -156,19 +156,14 @@ const GrabHelper = new Lang.Class({ if (this.isActorGrabbed(params.actor)) return true; - if (this._grabFocusCount == 0 && this._modalCount == 0) { - if (!this._fullGrab(hadFocus, params.modal, params.grabFocus)) - return false; - } - params.savedFocus = focus; this._grabStack.push(params); if (params.modal) - this._modalCount++; + this._takeModalGrab(hadFocus); if (params.grabFocus) - this._grabFocusCount++; + this._takeFocusGrab(hadFocus); if (hadFocus || params.grabFocus) _navigateActor(newFocus); @@ -176,34 +171,89 @@ const GrabHelper = new Lang.Class({ return true; }, - _fullGrab: function(hadFocus, modal, grabFocus) { - let metaDisplay = global.screen.get_display(); + _takeModalGrab: function(hadFocus) { + let firstGrab = (this._modalCount == 0); + this._modalCount++; + if (!firstGrab) + return; + + if (!Main.pushModal(this._owner)) + return; + + this._capturedEventId = global.stage.connect('captured-event', Lang.bind(this, this._onCapturedEvent)); + this._eventId = global.stage.connect('event', Lang.bind(this, this._onEvent)); + }, + + _releaseModalGrab: function() { + this._modalCount--; + if (this._modalCount > 0) + return; + + if (this._capturedEventId > 0) { + global.stage.disconnect(this._capturedEventId); + this._capturedEventId = 0; + } - if (modal) { - if (!Main.pushModal(this._owner)) - return false; + if (this._eventId > 0) { + global.stage.disconnect(this._eventId); + this._eventId = 0; } - this._grabbedFromKeynav = hadFocus; + Main.popModal(this._owner); + global.sync_pointer(); + }, + + _takeFocusGrab: function() { + let firstGrab = (this._grabFocusCount == 0); + this._grabFocusCount++; + if (!firstGrab) + return; + + let metaDisplay = global.screen.get_display(); + this._preGrabInputMode = global.stage_input_mode; - this._prevFocusedWindow = null; + this._prevFocusedWindow = metaDisplay.focus_window; - if (grabFocus) { - this._prevFocusedWindow = metaDisplay.focus_window; - if (this._preGrabInputMode == Shell.StageInputMode.NONREACTIVE || - this._preGrabInputMode == Shell.StageInputMode.NORMAL) { - global.set_stage_input_mode(Shell.StageInputMode.FOCUSED); - } + if (this._preGrabInputMode == Shell.StageInputMode.NONREACTIVE || + this._preGrabInputMode == Shell.StageInputMode.NORMAL) { + global.set_stage_input_mode(Shell.StageInputMode.FOCUSED); } - if (modal || grabFocus) { - this._capturedEventId = global.stage.connect('captured-event', Lang.bind(this, this._onCapturedEvent)); - this._eventId = global.stage.connect('event', Lang.bind(this, this._onEvent)); - this._keyFocusNotifyId = global.stage.connect('notify::key-focus', Lang.bind(this, this._onKeyFocusChanged)); - this._focusWindowChangedId = metaDisplay.connect('notify::focus-window', Lang.bind(this, this._focusWindowChanged)); + this._keyFocusNotifyId = global.stage.connect('notify::key-focus', Lang.bind(this, this._onKeyFocusChanged)); + this._focusWindowChangedId = metaDisplay.connect('notify::focus-window', Lang.bind(this, this._focusWindowChanged)); + }, + + _releaseFocusGrab: function() { + this._grabFocusCount--; + if (this._grabFocusCount > 0) + return; + + if (this._keyFocusNotifyId > 0) { + global.stage.disconnect(this._keyFocusNotifyId); + this._keyFocusNotifyId = 0; } - return true; + if (!this._focusWindowChanged > 0) { + let metaDisplay = global.screen.get_display(); + metaDisplay.disconnect(this._focusWindowChangedId); + this._focusWindowChangedId = 0; + } + + let prePopInputMode = global.stage_input_mode; + + if (this._grabbedFromKeynav) { + if (this._preGrabInputMode == Shell.StageInputMode.FOCUSED && + prePopInputMode != Shell.StageInputMode.FULLSCREEN) + global.set_stage_input_mode(Shell.StageInputMode.FOCUSED); + } + + if (this._prevFocusedWindow) { + let metaDisplay = global.screen.get_display(); + if (!metaDisplay.focus_window) { + metaDisplay.set_input_focus_window(this._prevFocusedWindow, + false, global.get_current_time()); + } + } }, // ignoreRelease: @@ -230,12 +280,14 @@ const GrabHelper = new Lang.Class({ if (grabStackIndex < 0) return; + let focus = global.stage.key_focus; + let hadFocus = focus && this._isWithinGrabbedActor(focus); + let poppedGrabs = this._grabStack.slice(grabStackIndex); // "Pop" all newly ungrabbed actors off the grab stack // by truncating the array. this._grabStack.length = grabStackIndex; - let wasModal = this._modalCount > 0; for (let i = poppedGrabs.length - 1; i >= 0; i--) { let poppedGrab = poppedGrabs[i]; @@ -243,65 +295,15 @@ const GrabHelper = new Lang.Class({ poppedGrab.onUngrab(); if (poppedGrab.modal) - this._modalCount--; + this._releaseModalGrab(); if (poppedGrab.grabFocus) - this._grabFocusCount--; + this._releaseFocusGrab(); } - let focus = global.stage.key_focus; - let hadFocus = focus && this._isWithinGrabbedActor(focus); - - if (this._grabFocusCount == 0 && this._modalCount == 0) - this._fullUngrab(wasModal); - - let poppedGrab = poppedGrabs[0]; - - if (hadFocus) + if (hadFocus) { + let poppedGrab = poppedGrabs[0]; _navigateActor(poppedGrab.savedFocus); - }, - - _fullUngrab: function(wasModal) { - if (this._capturedEventId > 0) { - global.stage.disconnect(this._capturedEventId); - this._capturedEventId = 0; - } - - if (this._eventId > 0) { - global.stage.disconnect(this._eventId); - this._eventId = 0; - } - - if (this._keyFocusNotifyId > 0) { - global.stage.disconnect(this._keyFocusNotifyId); - this._keyFocusNotifyId = 0; - } - - if (!this._focusWindowChanged > 0) { - let metaDisplay = global.screen.get_display(); - metaDisplay.disconnect(this._focusWindowChangedId); - this._focusWindowChangedId = 0; - } - - let prePopInputMode = global.stage_input_mode; - - if (wasModal) { - Main.popModal(this._owner); - global.sync_pointer(); - } - - if (this._grabbedFromKeynav) { - if (this._preGrabInputMode == Shell.StageInputMode.FOCUSED && - prePopInputMode != Shell.StageInputMode.FULLSCREEN) - global.set_stage_input_mode(Shell.StageInputMode.FOCUSED); - } - - if (this._prevFocusedWindow) { - let metaDisplay = global.screen.get_display(); - if (!metaDisplay.focus_window) { - metaDisplay.set_input_focus_window(this._prevFocusedWindow, - false, global.get_current_time()); - } } },